package com.yuandian.customer.perception.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.api.business_monitor.po.SearchParams;
import com.yuandian.api.customer_perception.po.StepFunctionRelationParams;
import com.yuandian.api.customer_perception.vo.StepFunctionRelationDetailVo;
import com.yuandian.api.customer_perception.vo.StepFunctionRelationOverviewVo;
import com.yuandian.api.management.feign.RemoteOptionService;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.customer.perception.mapper.StepFunctionRelationMapper;
import com.yuandian.customer.perception.service.IStepFunctionRelationService;
import com.yuandian.utils.*;
import com.yuandian.utils.poi.ExcelTitleUtils;
import com.yuandian.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p> 功能关联度 </p>
 *
 * @Author: LinSheHi
 * @Date: 2022/3/18 9:00
 */
@Slf4j
@Service
public class StepFunctionRelationServiceImpl implements IStepFunctionRelationService {

    @Autowired
    private StepFunctionRelationMapper stepFunctionRelationMapper;
	@Autowired
	private RemoteOptionService optionService;

    /**
     * 查询功能关联度总览
     * @param params
     * @return
     */
    @Override
    public R getStepFunctionRelationOverview(StepFunctionRelationParams params) {

        // 分类统计 所有跳转前URL+页签 对应的跳转次数总和   Map<跳转前URL@跳转前页签Id, 跳转总数>
        Map<String, Integer> map = getJumpTotalByBeforeUrlAndPageLabelId(params);

        // 查询数据
        List<StepFunctionRelationOverviewVo> list = stepFunctionRelationMapper.getStepFunctionRelationOverview(params);

        // 计算关联度 和 数据处理
        calculateCorrelationDegree(list, map);

        if (ListUtils.isNotNull(list) && ListUtils.isNotNull(params.getAdvancedQuery())) {
            // 如果前端进行了 ‘筛选’，则需要进行特殊处理
            list = advancedQuery(params, list);
        }


        // 若按照 关联度 排序则需查所有数据进行特殊排序和分页
        List<StepFunctionRelationOverviewVo> resList = new ArrayList<>();
        Comparator<StepFunctionRelationOverviewVo> comparator = null;
		Optional.of(params).ifPresent(e -> params.getQueryOperator());
        if ("desc".equalsIgnoreCase(params.getIsAsc())) {
            if ("correlationRatio".equalsIgnoreCase(params.getOrderByColumn())) {
                comparator = Comparator.comparing(StepFunctionRelationOverviewVo::getCorrelationRatio, Comparator.reverseOrder())
                        .thenComparing(StepFunctionRelationOverviewVo::getJumpTotal, Comparator.reverseOrder());
            } else {
                comparator = Comparator.comparing(StepFunctionRelationOverviewVo::getJumpTotal, Comparator.reverseOrder())
                        .thenComparing(StepFunctionRelationOverviewVo::getCorrelationRatio, Comparator.reverseOrder());
            }
        } else {
            if ("correlationRatio".equalsIgnoreCase(params.getOrderByColumn())) {
                comparator = Comparator.comparing(StepFunctionRelationOverviewVo::getCorrelationRatio)
                        .thenComparing(StepFunctionRelationOverviewVo::getJumpTotal);
            } else {
                comparator = Comparator.comparing(StepFunctionRelationOverviewVo::getJumpTotal)
                        .thenComparing(StepFunctionRelationOverviewVo::getCorrelationRatio);
            }
        }

        resList = list.stream().sorted(comparator).collect(Collectors.toList());
        int pNum = Long.valueOf(params.getPageNum()).intValue();
        int pSize = Long.valueOf(params.getPageSize()).intValue();
        int total = list.size();
        int from = (pNum - 1) * pSize;
        int to = pNum * pSize;
        if (to > total) {
            to = total;
        }

        // 由下载的接口进来时不用分页
        if (params.getPageSize() == -1) {
            // 初始化Excel序号用于导出
            int excelIndex = 1;
            for (StepFunctionRelationOverviewVo vo : resList) {
                // 用于导出Excel
                vo.setExcelIndex(excelIndex++);
            }
            return R.ok(new PageDataInfo(total, resList));
        }

        return R.ok(new PageDataInfo(total, resList.subList(from, to)));
    }

    /**
     * 高级筛选过滤
     * @param params
     * @param list
     * @return
     */
    private List<StepFunctionRelationOverviewVo> advancedQuery(StepFunctionRelationParams params,
                                                               List<StepFunctionRelationOverviewVo> list) {

        List<StepFunctionRelationOverviewVo> resList = new ArrayList<>();
        // 查询条件个数大于 1
        if (params.getAdvancedQuery().size() > 1) {
            if ("or".equalsIgnoreCase(params.getAdvancedQuery().get(1).getOperator())) {
                // or 操作
                if ("jumpTotal".equalsIgnoreCase(params.getAdvancedQuery().get(0).getColumn())) {

                    // 百分比转小数
                    String correlationRatioParamStr = params.getAdvancedQuery().get(1).getValue();
                    Double correlationRatioParamDou =  new BigDecimal((double) Double.parseDouble(correlationRatioParamStr) / 100).setScale(4, RoundingMode.HALF_UP).doubleValue();

                    for (StepFunctionRelationOverviewVo vo : list) {
                        // 进行数据比较
                        if (dataComparison(vo.getJumpTotal().doubleValue(),
                                params.getAdvancedQuery().get(0).getCondition(),
                                Double.parseDouble(params.getAdvancedQuery().get(0).getValue()))
                                || dataComparison(vo.getCorrelationRatio().doubleValue(),
                                params.getAdvancedQuery().get(1).getCondition(),
                                correlationRatioParamDou)) {

                            resList.add(vo);
                        }
                    }

                } else {
                    // 百分比转小数
                    String correlationRatioParamStr = params.getAdvancedQuery().get(0).getValue();
                    Double correlationRatioParamDou =  new BigDecimal((double) Double.parseDouble(correlationRatioParamStr) / 100).setScale(4, RoundingMode.HALF_UP).doubleValue();

                    for (StepFunctionRelationOverviewVo vo : list) {
                        // 进行数据比较
                        if (dataComparison(vo.getCorrelationRatio().doubleValue(),
                                params.getAdvancedQuery().get(0).getCondition(),
                                correlationRatioParamDou)
                                || dataComparison(vo.getJumpTotal().doubleValue(),
                                params.getAdvancedQuery().get(1).getCondition(),
                                Double.parseDouble(params.getAdvancedQuery().get(1).getValue()))) {

                            resList.add(vo);
                        }
                    }

                }
            } else {
                // and 操作
                if ("jumpTotal".equalsIgnoreCase(params.getAdvancedQuery().get(0).getColumn())) {
                    // 百分比转小数
                    String correlationRatioParamStr = params.getAdvancedQuery().get(1).getValue();
                    Double correlationRatioParamDou =  new BigDecimal((double) Double.parseDouble(correlationRatioParamStr) / 100).setScale(4, RoundingMode.HALF_UP).doubleValue();

                    for (StepFunctionRelationOverviewVo vo : list) {
                        // 进行数据比较
                        if (dataComparison(vo.getJumpTotal().doubleValue(),
                                params.getAdvancedQuery().get(0).getCondition(),
                                Double.parseDouble(params.getAdvancedQuery().get(0).getValue()))
                                && dataComparison(vo.getCorrelationRatio().doubleValue(),
                                params.getAdvancedQuery().get(1).getCondition(),
                                correlationRatioParamDou)) {

                            resList.add(vo);
                        }
                    }

                } else {

                    // 百分比转小数
                    String correlationRatioParamStr = params.getAdvancedQuery().get(0).getValue();
                    Double correlationRatioParamDou =  new BigDecimal((double) Double.parseDouble(correlationRatioParamStr) / 100).setScale(4, RoundingMode.HALF_UP).doubleValue();

                    for (StepFunctionRelationOverviewVo vo : list) {
                        // 进行数据比较
                        if (dataComparison(vo.getCorrelationRatio().doubleValue(),
                                params.getAdvancedQuery().get(0).getCondition(),
                                correlationRatioParamDou)
                                && dataComparison(vo.getJumpTotal().doubleValue(),
                                params.getAdvancedQuery().get(1).getCondition(),
                                Double.parseDouble(params.getAdvancedQuery().get(1).getValue()))) {

                            resList.add(vo);
                        }
                    }

                }
            }
        } else {

            if ("jumpTotal".equalsIgnoreCase(params.getAdvancedQuery().get(0).getColumn())) {
                for (StepFunctionRelationOverviewVo vo : list) {
                    // 进行数据比较
                    if (dataComparison(vo.getJumpTotal().doubleValue(),
                            params.getAdvancedQuery().get(0).getCondition(),
                            Double.parseDouble(params.getAdvancedQuery().get(0).getValue()))) {

                        resList.add(vo);
                    }
                }

            } else {
                // 百分比转小数
                String correlationRatioParamStr = params.getAdvancedQuery().get(0).getValue();
                Double correlationRatioParamDou =  new BigDecimal((double) Double.parseDouble(correlationRatioParamStr) / 100).setScale(4, RoundingMode.HALF_UP).doubleValue();

                for (StepFunctionRelationOverviewVo vo : list) {
                    // 进行数据比较
                    if (dataComparison(vo.getCorrelationRatio().doubleValue(),
                            params.getAdvancedQuery().get(0).getCondition(),
                            correlationRatioParamDou)) {

                        resList.add(vo);
                    }
                }

            }
        }

        return resList;
    }


    /**
     * 进行数据比较
     * @param doubleValue
     * @param condition
     * @param parseDouble
     * @return
     */
    private boolean dataComparison(double doubleValue, int condition, double parseDouble) {
        boolean flag = false;

        switch (condition) {
            case 1 :
                flag = doubleValue > parseDouble;
                break;
            case 2 :
                flag = doubleValue < parseDouble;
                break;
            case 3 :
                flag = doubleValue == parseDouble;
                break;
            case 4 :
                flag = doubleValue >= parseDouble;
                break;
            case 5 :
                flag = doubleValue <= parseDouble;
        }

        return flag;
    }

    /**
     * 下载功能关联度总览
     * @param params
     * @param response
     */
    @Override
    public void getStepFunctionRelationOverviewExcel(StepFunctionRelationParams params, HttpServletResponse response) {
        ExcelWriter excelWriter = null;
        try {

            // 实例化 ExcelWriter 对象
            excelWriter = EasyExcel.write(response.getOutputStream()).build();

            // 1、查询要导出的数据
            params.setPageNum(1);
            params.setPageSize(-1);
            PageDataInfo pageDataInfo = BeanUtils.cast(getStepFunctionRelationOverview(params).getData());
            List<StepFunctionRelationOverviewVo> list = new ArrayList<>();
            if (!Objects.isNull(pageDataInfo)) {
                list = BeanUtils.cast(pageDataInfo.getData());
            }

            for (StepFunctionRelationOverviewVo vo : list) {
                if (StringUtils.isEmpty(vo.getOperatorId())) {
                    vo.setOperatorId("-");
                    vo.setOperatorName("-");
                } else if (StringUtils.isEmpty(vo.getOperatorName())) {
                    vo.setOperatorName("未知");
                }
                // 页签名称为空回填'-'
                if (StringUtils.isEmpty(vo.getBeforePageLabelName())) { vo.setBeforePageLabelName("-"); }
                if (StringUtils.isEmpty(vo.getAfterPageLabelName())) { vo.setAfterPageLabelName("-"); }

                // 菜单名称为空回填'-'
                if (StringUtils.isEmpty(vo.getBeforeMenuName())) { vo.setBeforeMenuName("-"); }
                if (StringUtils.isEmpty(vo.getAfterMenuName())) { vo.setAfterMenuName("-"); }

                // URL为空回填'-'
                if (StringUtils.isEmpty(vo.getBeforeUrlApi())) { vo.setBeforeUrlApi("-"); }
                if (StringUtils.isEmpty(vo.getAfterUrlApi())) { vo.setAfterUrlApi("-"); }

            }

            //设置表头
            List<String> headParamsList = new ArrayList<>();
            String title = "功能关联度总览表";
            String fileName = title + System.currentTimeMillis();
            String sheetName = title;
            headParamsList.add(title);
            String formTitleName = ExcelTitleUtils.formTitleName(headParamsList, params.getStartTime(), params.getEndTime());

            List<List<String>> headList = new ArrayList<>();
            List<String> titleList = getTitle(params);

            titleList.forEach(s -> {
                List<String> childHeadList = new ArrayList<>();
                childHeadList.add(formTitleName);
                childHeadList.add(s);
                headList.add(childHeadList);
            });

            if (params.getQueryOperator() == 0) {
                ExcelUtil.writeOnly(excelWriter, list, headList, Arrays.asList("operatorId", "operatorName"),
                        StepFunctionRelationOverviewVo.class, 0, title);
            }else {
                ExcelUtil.writeOnly(excelWriter, list, headList, null,
                        StepFunctionRelationOverviewVo.class, 0, title);
            }
            // 返回文件流
            ExcelUtil.writeExcel("功能关联度总览表", response);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (excelWriter != null) {
                try {
                    response.getOutputStream().flush();
                    excelWriter.finish();
                    response.getOutputStream().close();
                }catch (Exception e) {
                    log.error("IO流关闭异常： " + e.getMessage());
                }
            }
        }

    }

    /**
     * 获取标题
     * @param params
     * @return
     */
    private List<String> getTitle(StepFunctionRelationParams params) {
        List<String> titleList = new ArrayList<>();
        if (params.getQueryOperator() == 0) {
            titleList = Arrays.asList("序号",  "跳转前URL", "系统名称", "菜单名称", "页签", "跳转后URL", "系统名称","菜单名称", "页签", "跳转次数", "关联度比例");
        }else {
            titleList = Arrays.asList("序号", "用户标识", "用户名", "跳转前URL", "系统名称",  "菜单名称", "页签", "跳转后URL", "系统名称", "菜单名称", "页签", "跳转次数", "关联度比例");
        }
        return titleList;
    }

    /**
     * 构造 key, 从 Map<String: 跳转前URL@跳转前menuId@跳转前页签ID, Integer: 跳转次数 > 中获取对应的跳转次数
     * @param overviewVo
     * @return
     */
    private static String getMapKey(StepFunctionRelationOverviewVo overviewVo) {
        String mapKey = "";

        if (StringUtils.isNotEmpty(overviewVo.getBeforeMenuId()) && StringUtils.isNotEmpty(overviewVo.getBeforePageLabelId())) {
            // 菜单id 和 页签Id 都不为空
            mapKey = overviewVo.getBeforeUrlApi() + "@" + overviewVo.getBeforeMenuId() + "@" + overviewVo.getBeforePageLabelId();

        }else if (StringUtils.isNotEmpty(overviewVo.getBeforeMenuId()) && StringUtils.isEmpty(overviewVo.getBeforePageLabelId())) {
            // 菜单id 不为空 和 页签Id 为空
            mapKey = overviewVo.getBeforeUrlApi() + "@" + overviewVo.getBeforeMenuId();

        }else if (StringUtils.isEmpty(overviewVo.getBeforeMenuId()) && StringUtils.isNotEmpty(overviewVo.getBeforePageLabelId())) {
            // 菜单id 为空 和 页签Id 不为空
            mapKey = overviewVo.getBeforeUrlApi() + "@" + overviewVo.getBeforePageLabelId();

        }else if (StringUtils.isEmpty(overviewVo.getBeforeMenuId()) && StringUtils.isEmpty(overviewVo.getBeforePageLabelId())) {
            // 菜单id 和 页签Id 都为空
            mapKey = overviewVo.getBeforeUrlApi();
        }

        return mapKey;

    }
    /**
     * 计算关联度 和 回填页签名称
     * @param list  结果集
     * @param map   关联度集合 Map<跳转前URL@跳转前页签Id, 跳转总数>
     */
    private void calculateCorrelationDegree(List<StepFunctionRelationOverviewVo> list, Map<String, Integer> map) {

        if (ListUtils.isNotNull(list)) {
            for (StepFunctionRelationOverviewVo overviewVo : list) {
                String mapKey = getMapKey(overviewVo);
                // 计算并回填关联度比例
                overviewVo.setCorrelationRatio(MathUtil.division(overviewVo.getJumpTotal(), map.get(mapKey)));

                // 如果页签名称为空则需要去哦回填页签ID
                if (StringUtils.isEmpty(overviewVo.getBeforePageLabelName())) {
                    overviewVo.setBeforePageLabelName(overviewVo.getBeforePageLabelId());
                }

                if (StringUtils.isEmpty(overviewVo.getAfterPageLabelName())) {
                    overviewVo.setAfterPageLabelName(overviewVo.getAfterPageLabelId());
                }

                overviewVo.setCorrelationRatioStr(MathUtil.getDoubleRes(overviewVo.getCorrelationRatio()) + "%");

                // 如果查询出来的用户Id为 ‘000000’ 则需要置为空，因为‘000000’是为了方便SQL计算，实际是没有采集操用户ID的
                if ("000000".equals(overviewVo.getOperatorId())) {
                    overviewVo.setOperatorId(null);
                }
            }
        }

    }

    /**
     * 查询功能关联度详情
     * @param params
     * @return
     */
    @Override
    public PageDataInfo getStepFunctionRelationDetail(StepFunctionRelationParams params) {
        // 如果要查询具体某个用户的关联度明细，而该前端用户ID参数又为空的话，那么需要查询用户Id 为 ‘000000’ 的数据,因为数据表里面 ‘000000’代表用户ID为空
        if (params.getQueryOperator() == 1 && StringUtils.isEmpty(params.getOperatorId())) {
            params.setOperatorId("000000");
        }

        Page<StepFunctionRelationDetailVo> page = new Page<>(params.getPageNum(), params.getPageSize());

        List<StepFunctionRelationDetailVo> list = stepFunctionRelationMapper.getStepFunctionRelationDetail(page, params);
        // 初始化Excel序号,用于下载
        int excelIndex = 1;
        for (StepFunctionRelationDetailVo vo : list) {
            if (StringUtils.isEmpty(vo.getBeforePageLabelName())) {
                vo.setBeforePageLabelName(vo.getBeforePageLabelId());
            }
            if (StringUtils.isEmpty(vo.getAfterPageLabelName())) {
                vo.setAfterPageLabelName(vo.getAfterPageLabelId());
            }
            vo.setExcelIndex(excelIndex++);
            // 如果查询出来的用户Id为 ‘000000’ 则需要置为空，因为‘000000’是为了方便SQL计算，实际是没有采集操用户ID的
            if ("000000".equals(vo.getOperatorId())) {
                vo.setOperatorId(null);
            }
            vo.setJumpTime(DateTool.interceptionTime(vo.getJumpTime()));
        }
        return new PageDataInfo(page, list);
    }

    /**
     * 下载功能关联度详情
     * @param params
     * @param response
     */
    @Override
    public void getStepFunctionRelationDetailExcel(StepFunctionRelationParams params, HttpServletResponse response) {

    }


    /**
     * 分类统计 所有跳转天URL+页签 对应的跳转次数总和
     *          Map<跳转前URL@跳转前页签Id, 跳转总数>
     *
     * @param params
     * @return
     */
    private Map<String, Integer> getJumpTotalByBeforeUrlAndPageLabelId(StepFunctionRelationParams params) {
        Map<String, Integer> map = new HashMap<>();
        List<Map<String, Object>> list = stepFunctionRelationMapper.getJumpTotalByBeforeUrlAndPageLabelId(params);
        if (ListUtils.isNotNull(list)) {
            for (Map<String, Object> objectMap : list) {
                map.put(String.valueOf(objectMap.get("urlAndPageLabel")), Integer.parseInt(String.valueOf(objectMap.get("jumpTotal"))));
            }
        }
        return map;
    }

    /**
     * 获取菜单信息
     * @param params
     * @return
     */
    public R getMenuInfoList(StepFunctionRelationParams params) {

        // 查询数据
        SearchParams searchParams = new SearchParams();
        if (params != null && params.getSystemId() != null) {
            searchParams.setSystemId(params.getSystemId().toString());
        }
//    todo    List<Map<String, Object>> menuInfoList = optionService.system(searchParams);

        return R.ok();
    }


}
